package com.ludomancy.gamelib.verlet;

public class Edge
{
	public Vertex v1;
	public Vertex v2;
	public float restLength;
	public float restLengthSq;
	public float radii;
	
	public Edge(Vertex v1, Vertex v2)
	{
		this.v1 = v1;
		this.v2 = v2;
		restLength = length();
		restLengthSq = lengthSq();
		this.radii = Math.max(v1.radii, v2.radii);
		v1.edges.add(this);
		v2.edges.add(this);
	}
	
	public void destroy()
	{
		v1.edges.remove(this);
		v2.edges.remove(this);
	}
		
	public void moveAtPoint(float t, float x, float y)
	{
		float lambda = 1+2*(t*t-t);
		if(!v1.fixed)
		{
			v1.px += (1-t)*x/lambda;
			v1.py += (1-t)*y/lambda;
		}
		
		if(!v2.fixed)
		{
			v2.px += t*x/lambda;
			v2.py += t*y/lambda;
		}
		
		if(!v1.fixed)
		{
			v1.old_px += (1-t)*x/lambda;
			v1.old_py += (1-t)*y/lambda;
		}
		
		if(!v2.fixed)
		{
			v2.old_px += t*x/lambda;
			v2.old_py += t*y/lambda;
		}
	}
	
	public float effort()
	{
		return restLengthSq/lengthSq();
	}

	void ensureLength()
	{
		float pushx = (v1.px - v2.px);
		float pushy = (v1.py - v2.py);
		float invMass1 = v1.fixed ? 0 : 1;
		float invMass2 = v2.fixed ? 0 : 1;
		if(invMass1 + invMass2 == 0)
			return;
		float delta = (float)Math.sqrt((pushx*pushx)+(pushy*pushy));
		float diff = (delta - restLength)/(delta*(invMass1+invMass2));
		v1.px -= invMass1 * pushx * diff;
		v1.py -= invMass1 * pushy * diff;
		v2.px += invMass2 * pushx * diff;
		v2.py += invMass2 * pushy * diff;
	}
	
	void ensureLength2()
	{
		float pushx = (v1.px - v2.px);
		float pushy = (v1.py - v2.py);
		float delta = pushx*pushx + pushy*pushy;
		pushx *= restLengthSq / (delta + restLengthSq) - 0.5;
		pushy *= restLengthSq / (delta + restLengthSq) - 0.5;
		if(!v1.fixed && !v2.fixed)
		{
			v1.px += pushx;
			v1.py += pushy;
			v2.px -= pushx;
			v2.py -= pushy;
		}
		else
		if(v1.fixed)
		{
			v2.px -= pushx+pushx;
			v2.py -= pushy+pushy;			
		}
		else
		if(v2.fixed)
		{
			v1.px += pushx + pushx;
			v1.py += pushy + pushy;
		}
	}
	
	public void pushAtPoint(float t, float x, float y)
	{
		float lambda = (1-t)*(1-t) + t*t;
		if(!v1.fixed)
		{
			v1.px += (1-t)*x/lambda;
			v1.py += (1-t)*y/lambda;
		}
		
		if(!v2.fixed)
		{
			v2.px += t*x/lambda;
			v2.py += t*y/lambda;
		}
	}
		
	public void setVelocityAtPoint(float t, float x, float y)
	{
		v1.old_px = v1.px - x*(1-t) - v1.velX()*t;
		v1.old_py = v1.py - y*(1-t) - v1.velY()*t;
		
		v2.old_px = v2.px - x*t - v2.velX()*(1-t);
		v2.old_py = v2.py - y*t - v2.velY()*(1-t);
	}

	public float lengthSq()
	{
		float ox = v1.px - v2.px;
		float oy = v1.py - v2.py;
		return ox*ox + oy*oy;
	}
	
	public float length()
	{
		float ox = v1.px - v2.px;
		float oy = v1.py - v2.py;
		return (float)Math.sqrt(ox*ox + oy*oy);
	}
}
